home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
mail
/
readers
/
xmail_1.000
/
xmail_1
/
xmail_1.6
/
utils.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-30
|
14KB
|
480 lines
/*
* xmail - X window system interface to the mail program
*
* Copyright 1990,1991,1992 by National Semiconductor Corporation
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of National Semiconductor Corporation not
* be used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
* SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS"
* WITHOUT EXPRESS OR IMPLIED WARRANTY. NATIONAL SEMICONDUCTOR CORPORATION
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
* EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* The following software modules were created and are Copyrighted by
* National Semiconductor Corporation:
*
* 1. markIndex:
* 2. LastNumber:
* 3. SelectionNumber:
* 4. SetCursor: and
* 5. SetXY.
*
* Author: Michael C. Wagnitz - National Semiconductor Corporation
*
*/
#include <ctype.h>
#include "global.h"
#include "patchlevel.h"
#include "revtable.h"
/*
** @(#)Bell() - write a status message and (optionally) ring the terminal bell
*/
void
Bell(String msg)
{
Arg args[1];
char *p;
char buf[BUFSIZ];
int size;
static int worthy = 0; /* only msgs with ending newline are */
size = (int)strlen(msg);
if (size >= BUFSIZ) size = BUFSIZ - 1;
(void) strncpy(buf, msg, size);
buf[size] = '\0';
p = strchr(buf, '\n'); /* messages with newline get a bell */
/*
** Because we have now added enter/leave window event information messages,
** we must play a slight game with incoming messages, to prevent any error
** messages from a menu selection failure or status messages from a command
** button being overwritten by the subsequent event info messages produced
** when the menu popup is dismissed or the command completes. To do this,
** we make the bell worthy-ness flag static, and only replace a message after
** first seeing a non-default status message, which will reset the worthy-ness
** flag, but otherwise be ignored. When the first non-default, non-error
** message comes in, simply reset our bell worthy-ness flag and return, leaving
** the previous error message still intact. This means, to ensure seeing the
** default message, first send a blank line to reset the worthy-ness flag.
*/
if (! XMail.Show_Info) /* if NOT showing info flags always */
worthy = 0; /* reset the bell worthy-ness flag */
else {
if (worthy && p == NULL) { /* if last was but this ain't urgent */
if (strcmp(buf, Default_Status_Info)) /* and not the default info */
worthy = 0; /* reset the bell worthy-ness flag */
return; /* ignore event info if menu errored */
} /* by leaving previous error message */
}
if (size == 0) /* if intent was just to reset flag */
return;
if (p != NULL) { /* Only display first line of output */
*p = '\0'; /* (no new line at end of label) */
worthy = 1; /* this message is worthy of a bell */
}
if (worthy && XMail.bellRing) /* ring bell if not silenced by user */
XBell(XtDisplay (toplevel), 33);
XtSetArg(args[0], XtNlabel, (XtArgVal) buf); /* show this message text */
XtSetValues(XtNameToWidget(toplevel, "topBox.statusWindow"), args, 1);
XFlush(XtDisplay(toplevel));
} /* Bell */
/*
** @(#)figureWidth() - determine the figure width of the specified font
*/
int
figureWidth(XFontStruct *font)
{
Atom _XA_FIGURE_WIDTH;
unsigned long width = 0;
_XA_FIGURE_WIDTH = XInternAtom(XtDisplay(toplevel), "FIGURE_WIDTH", FALSE);
if ((_XA_FIGURE_WIDTH != (Atom)NULL) &&
((! XGetFontProperty(font, _XA_FIGURE_WIDTH, &width)) || (width == 0)))
if (font->per_char && font->min_char_or_byte2 <= '$' &&
font->max_char_or_byte2 >= '$')
width = font->per_char['$' - font->min_char_or_byte2].width;
else
width = font->max_bounds.width;
return(width);
} /* end - figureWidth */
/*
** @(#)markIndex() - add or remove a tag from the start of a mail header line
** May be invoked by button press, which sets the insertion
** pointer for the text to the current mouse cursor location.
*/
void
markIndex(char *s)
{
int size;
XawTextPosition pos, old;
String c, p = NULL;
char buf[3];
Widget iw = XtNameToWidget(toplevel, "topBox.indexWindow");
Arg args[1];
XawTextBlock text;
(void) strcpy(buf, s); /* make a copy of our marker string */
XtSetArg(args[0], XtNstring, &p); /* retrieve the current index buffer */
XtGetValues(iw, args, 1);
for (pos = XawTextGetInsertionPoint(iw); pos > 0 && p[pos-1] != '\n'; pos--);
if (buf[0] == '>') { /* if mark is for 'current' pointer */
XtSetArg(args[0], XtNstring, &p); /* retrieve the current index buffer */
XtGetValues(iw, args, 1);
if ((int)strlen(p) < 3) /* trap for case of no index at all */
return;
if ((int)strlen(p) > pos + 1)
if (p[pos + 1] == 'S') /* keep the Save marker if it exists */
if ((int)strlen(buf) > 1)
buf[1] = '\0';
for (c = p; *c; c++)
if (*c == '>' && (c == p || *(c - 1) == '\n')) {
old = c - p; /* if found, remove the old '>' mark */
text.firstPos = 0;
text.length = 1;
text.ptr = " ";
text.format = FMT8BIT;
XawTextReplace(iw, (XawTextPosition) old, (XawTextPosition) old + 1, &text);
break;
}
}
size = (int)strlen(buf); /* now write the specified marker */
old = (buf[0] == '>') ? pos : pos + 1;
text.firstPos = 0;
text.length = size;
text.ptr = buf;
text.format = FMT8BIT;
XawTextReplace(iw, (XawTextPosition) old, (XawTextPosition) old + size, &text);
XawTextSetInsertionPoint(iw, pos); /* reset our actual insertion point */
} /* markIndex */
/*
** @(#)LastNumber() - Get mail index number for last message in folder
*/
int
LastNumber(void)
{
int last_number;
Arg args[1];
String c, ep, str = NULL;
Widget iw = XtNameToWidget(toplevel, "topBox.indexWindow");
XtSetArg(args[0], XtNstring, &str);
XtGetValues(iw, args, 1);
ep = &str[(int)strlen(str) - 1];
for (c = ep - 1; c > str; c--)
if (*(c - 1) == '\n' && *(c + 1) != 'D')
break;
for (; c < ep && !isdigit(*c); c++);
(void) sscanf(c, "%d", &last_number);
return(last_number);
} /* LastNumber */
/*
** @(#)SelectionNumber() - Get mail index number from line position
*/
int
SelectionNumber(int undeleting)
{
Arg args[1];
String c, str = NULL;
Widget iw = XtNameToWidget(toplevel, "topBox.indexWindow");
XawTextPosition pos;
int selection_number = 0;
XtSetArg(args[0], XtNstring, &str);
XtGetValues(iw, args, 1);
for (pos = XawTextGetInsertionPoint(iw); pos > 0 && str[pos] != '\n'; pos--);
pos++;
if (! undeleting || str[pos + 1] == 'D') {
for (c = &str[pos]; *c && !isdigit(*c); c++);
(void) sscanf(c, "%d", &selection_number);
}
return(selection_number);
} /* SelectionNumber */
/* ARGSUSED */
/*
** @(#)SetCursor() - sets the wait cursor or restores the default
*/
void
SetCursor(int waiting)
/* a non-zero value sets the busy cursor */
{
if (! waiting)
XUnmapWindow(XtDisplay(toplevel), WaitCursorWindow);
else {
XMapWindow(XtDisplay(toplevel), WaitCursorWindow);
Waiting = TRUE; /* to prevent overwrite of important info */
}
XFlush(XtDisplay(toplevel));
} /* SetCursor */
/*
** @(#)SetXY() - Set relative window coordinates including specified offset
*/
void
SetXY(Widget target, Widget reference, int X_offset, int Y_offset)
{
Arg args[2];
Display *dpy = XtDisplay(reference);
Window dumy;
int x, y;
XTranslateCoordinates(dpy, XtWindow(reference),
RootWindow(dpy, DefaultScreen(dpy)),
X_offset, Y_offset, &x, &y, &dumy);
/*
** Keep window within root window borders (don't place it off-screen)
*/
if (! XtIsRealized(target))
XtRealizeWidget(target); /* to get width and height values */
if (x + (int) target->core.width > RootWidth)
x = RootWidth - target->core.width - 2;
if (y + (int)target->core.height > RootHeight)
y = RootHeight - target->core.height - 2;
XtSetArg(args[0], XtNx, x);
XtSetArg(args[1], XtNy, y);
XtSetValues(target, args, 2);
} /* end - SetXY */
/*
** @(#)TextGetLastPos() - return position of last text character
*/
XawTextPosition
TextGetLastPos(Widget w)
{
TextWidget ctx = (TextWidget) w;
if (ctx->text.source)
return (XawTextSourceScan(ctx->text.source,0,XawstAll,XawsdRight,1,TRUE));
else
return( (XawTextPosition) 0);
}
/*
** @(#)UpdateTitleBar() - replace information in the title bar title
*/
void
UpdateTitleBar(char *msg)
{
char message[BUFSIZ];
Arg args[1];
Widget w;
(void) sprintf(message, "%s%d - %s", TITLE, PATCHLEVEL, msg);
w = XtNameToWidget(toplevel, "topBox.titleBar.title");
XtSetArg(args[0], XtNlabel, (XtArgVal) message);
XtSetValues(w, args, 1);
w = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail.Newmail_menu.menu.inc");
if (w)
XtSetSensitive(w, In_System_Folder());
} /* UpdateTitleBar */
/*
** @(#)writeTo() - write data to the specified text widget
*/
void
writeTo(Widget w, char *data, int do_append)
{
XawTextBlock text;
XawTextPosition startPos, endPos;
int l, n;
endPos = TextGetLastPos(w) + (do_append ? 0 : 1);
startPos = (do_append ? endPos : 0);
text.firstPos = 0;
text.length = (int)strlen(data);
text.ptr = data;
text.format = FMT8BIT;
XawTextReplace(w, (XawTextPosition) startPos, (XawTextPosition) endPos, &text);
XawTextSetInsertionPoint(w, (XawTextPosition) TextGetLastPos(w));
XawTextInvalidate(w, (XawTextPosition) 0, (XawTextPosition) endPos);
} /* writeTo */
/*
** @(#)writeText() - replace the current text string in the text window.
** Also look for an X-Face: header and if found, display.
*/
void
writeText(char *buf)
{
Arg args[2];
Widget w = XtNameToWidget(toplevel, "topBox.textWindow.text");
#ifdef X_FACE
Pixmap bits;
Dimension rWidth;
Display *dpy = XtDisplay(w);
Widget fw;
Window rw;
char cb[1024], fb[2048], *ptr, *xface;
int i, n, x, y;
#endif
if (buf && *buf) {
#ifndef X_FACE
XtSetArg(args[0], XtNstring, buf);
XtSetValues(w, args, 1);
#else
if (! (fw = XtNameToWidget(XtParent(w), "face"))) {
XtSetArg(args[0], XtNstring, buf);
XtSetValues(w, args, 1);
return;
}
/*
** First, unmap any current picture.
**
** Look for a line containing an 'X-Face:' header, followed by 72
** characters of compressed data. The second and any subsequent lines
** will contain an initial space (which is ignored), followed by 79
** characters of compressed data. The last line may contain fewer than 79
** characters.
**
** The X-Face: header and any immediate whitespace (tabs or spaces) will be
** removed, and the remaining line placed in the internal buffer (minus
** any trailing newline). On subsequent lines, initial whitespace will be
** removed, and the remainder of the data appended to the buffer (minus any
** trailing newline).
**
** A blank line, a line without an initial whitespace character,or the
** end of the input buffer will signify the end of the X-Face data. That
** buffer will then be uncompressed, and if the data was valid, displayed.
*/
if (XtIsManaged(fw))
XtUnmanageChild(fw);
for (ptr = buf; *ptr; ptr++) {
if (*ptr == '\n' ||
strncmp(ptr, "Status:", 7) == 0 ||
strncmp(ptr, "X-Face:", 7) == 0) break;
for (; *ptr && *ptr != '\n'; ptr++);
}
if (! *ptr || strncmp(ptr, "X-Face:", 7) != 0) {
XtSetArg(args[0], XtNstring, buf);
XtSetValues(w, args, 1);
return;
}
xface = ptr; /* keep track of the start position of X-Face header */
bzero(fb, 2048);
for (i = 0, ptr += 7; *ptr; ptr++) {
if (*ptr != ' ' && *ptr != '\t' && *ptr != '\n')
fb[i++] = *ptr;
if (*ptr == '\n' && *(ptr+1) && *(ptr+1) != ' ' && *(ptr+1) != '\t')
break;
}
if (XMail.No_X_Hdr) {
if (*ptr) ptr++;
bcopy(ptr, xface, (int)strlen(ptr) + 1); /* suppress the X-Face header */
}
XtSetArg(args[0], XtNstring, buf);
XtSetValues(w, args, 1);
if (uncompface(fb) >= 0) {
bzero(cb, 1024);
for (i = n = 0;i < 1024;) {
if (! sscanf(&fb[n], "%i%n", &x, &y)) break;
cb[i++] = revtable[(x >> 8) & 0xFF];
cb[i++] = revtable[x & 0xFF];
n += y;
while (fb[n] && (fb[n]==',' || fb[n]=='\n')) n++;
}
XtSetArg(args[0], XtNwidth, &rWidth);
XtGetValues(XtParent(w), args, 1);
if ( (int)rWidth > 0 )
n = (int) rWidth - 52; /* the width of the face minus 4 pixel inset */
else
n = 0;
XtSetArg(args[0], XtNbitmap, &bits);
XtGetValues(fw, args, 1);
if (bits != None)
XFreePixmap(dpy, bits );
rw = RootWindow(dpy, DefaultScreen(dpy));
bits = XCreateBitmapFromData(dpy, rw, cb, 48, 48);
XtSetArg(args[0], XtNbitmap, bits );
XtSetArg(args[1], XtNhorizDistance, n);
XtSetValues(fw, args, 2);
XtManageChild(fw);
}
#endif
}
} /* writeText */